package com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.repository;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowBusi;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowBusiAddVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowBusiUpdateVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowBusiRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.InitCreatorRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.entities.FlowBusiInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.entities.FlowBusiInfoExample;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.mapper.FlowBusiInfoDAO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

/**
 * Service - 业务服务
 *
 * @author lilh
 * @date 2019-01-22 16:35
 */
@Repository
public class FlowBusiRepositoryImpl implements FlowBusiRepository {

    @Autowired
    private FlowBusiInfoDAO flowBusiInfoDAO;

    @Autowired
    private InitCreatorRepository initCreatorRepository;

    @Override
    public Integer insert(FlowBusiAddVo flowBusiAddVo) {
        FlowBusiInfo entity = new FlowBusiInfo();
        BeanUtils.copyProperties(flowBusiAddVo, entity);
        FlowBusiInfoExample example = new FlowBusiInfoExample();
        example.createCriteria().andAppIdEqualTo(entity.getAppId()).andBusiNameEqualTo(entity.getBusiName());
        Lock lock = new ReentrantLock();
        lock.lock();
        try {
            List<FlowBusiInfo> list = flowBusiInfoDAO.selectByExample(example);
            if (CollectionUtils.isNotEmpty(list)) {
                return 0;
            }
            initCreatorRepository.init(entity);
            flowBusiInfoDAO.insertSelective(entity);
        } finally {
            lock.unlock();
        }
        return 1;
    }

    @Override
    public List<FlowBusi> list(Integer appId) {
        FlowBusiInfoExample busiInfoExample = new FlowBusiInfoExample();
        busiInfoExample.createCriteria().andAppIdEqualTo(appId);
        return flowBusiInfoDAO.selectByExample(busiInfoExample).stream().map(this::convert).collect(Collectors.toList());
    }

    @Override
    public List<FlowBusi> list(List<Integer> appIds) {
        FlowBusiInfoExample busiInfoExample = new FlowBusiInfoExample();
        busiInfoExample.createCriteria().andAppIdIn(appIds);
        return flowBusiInfoDAO.selectByExample(busiInfoExample).stream().map(this::convert).collect(Collectors.toList());
    }

    @Override
    public FlowBusi detail(Integer busiId) {
        return convert(flowBusiInfoDAO.selectByPrimaryKey(busiId));
    }

    @Override
    public boolean update(FlowBusiUpdateVo flowBusiUpdateVo) {
        FlowBusiInfo busiInfo = flowBusiInfoDAO.selectByPrimaryKey(flowBusiUpdateVo.getId());
        if (Objects.isNull(busiInfo)) {
            throw new IllegalArgumentException("业务不存在");
        }
        FlowBusiInfo flowBusiInfo = new FlowBusiInfo();
        BeanUtils.copyProperties(flowBusiUpdateVo, flowBusiInfo);
        flowBusiInfo.setUpdateTime(new Date());
        FlowBusiInfoExample example = new FlowBusiInfoExample();
        example.createCriteria().andAppIdEqualTo(busiInfo.getAppId()).andBusiNameEqualTo(flowBusiInfo.getBusiName());
        Lock lock = new ReentrantLock();
        lock.lock();
        try {
            List<FlowBusiInfo> list = flowBusiInfoDAO.selectByExample(example);
            if (CollectionUtils.isNotEmpty(list)) {
                FlowBusiInfo info = list.get(0);
                if (list.size() > 1 || !info.getId().equals(busiInfo.getId())) {
                    throw new IllegalArgumentException("业务名称重复");
                }
            }
            flowBusiInfoDAO.updateByPrimaryKeySelective(flowBusiInfo);
        } finally {
            lock.unlock();
        }
        return true;
    }

    @Override
    public Integer delete(Integer busiId) {
        return flowBusiInfoDAO.deleteByPrimaryKey(busiId);
    }

    private FlowBusi convert(FlowBusiInfo info) {
        if (Objects.nonNull(info)) {
            FlowBusi busi = new FlowBusi();
            BeanUtils.copyProperties(info, busi);
            return busi;
        }
        return null;
    }
}
